import logging
import requests
from string import Template

from bi.destinations import *
from bi.utils import json_dumps
from bi.serializers import serialize_alert


def json_string_substitute(j, substitutions):
    """
    Alternative to string.format when the string has braces.
    :param j: json string that will have substitutions
    :type j: str
    :param substitutions: dictionary of values to be replaced
    :type substitutions: dict
    """
    if substitutions:
        substitution_candidate = j.replace("{", "${")
        string_template = Template(substitution_candidate)
        substituted = string_template.safe_substitute(substitutions)
        out_str = substituted.replace("${", "{")
        return out_str
    else:
        return j


class MicrosoftTeamsWebhook(BaseDestination):
    ALERTS_DEFAULT_MESSAGE_TEMPLATE = json_dumps({
        "@type": "MessageCard",
        "@context": "http://schema.org/extensions",
        "themeColor": "0076D7",
        "summary": "A BI Alert was Triggered",
        "sections": [{
            "activityTitle": "A BI Alert was Triggered",
            "facts": [{
                "name": "Alert Name",
                "value": "{alert_name}"
            }, {
                "name": "Alert URL",
                "value": "{alert_url}"
            }, {
                "name": "Query",
                "value": "{query_text}"
            }, {
                "name": "Query URL",
                "value": "{query_url}"
            }],
            "markdown": True
        }]
    })


    @classmethod
    def name(cls):
        return "Microsoft Teams Webhook"

    @classmethod
    def type(cls):
        return "microsoft_teams_webhook"

    @classmethod
    def configuration_schema(cls):
        return {
            "type": "object",
            "properties": {
                "url": {
                    "type": "string",
                    "title": "Microsoft Teams Webhook URL"
                },
                "message_template": {
                    "type": "string",
                    "default": MicrosoftTeamsWebhook.ALERTS_DEFAULT_MESSAGE_TEMPLATE,
                    "title": "Message Template",
                },
            },
            "required": ["url"],
        }

    @classmethod
    def icon(cls):
        return "fa-bolt"

    def notify(self, alert, query, user, new_state, app, host, options):
        """
        :type app: bi.Bi
        """
        try:
            alert_url = "{host}/alerts/{alert_id}".format(
                host=host, alert_id=alert.id
            )

            query_url = "{host}/queries/{query_id}".format(
                host=host, query_id=query.id
            )

            message_template = options.get(
                "message_template", MicrosoftTeamsWebhook.ALERTS_DEFAULT_MESSAGE_TEMPLATE
            )

            # Doing a string Template substitution here because the template contains braces, which
            # result in keyerrors when attempting string.format
            payload = json_string_substitute(message_template, {
                "alert_name": alert.name,
                "alert_url": alert_url,
                "query_text": query.query_text,
                "query_url": query_url
            })

            headers = {"Content-Type": "application/json"}

            resp = requests.post(
                options.get("url"),
                data=payload,
                headers=headers,
                timeout=5.0,
            )
            if resp.status_code != 200:
                logging.error(
                    "MS Teams Webhook send ERROR. status_code => {status}".format(
                        status=resp.status_code
                    )
                )
        except Exception:
            logging.exception("MS Teams Webhook send ERROR.")


register(MicrosoftTeamsWebhook)
